package com.springboot.shiro.config.redis;

import com.springboot.shiro.pojo.User;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @Date: 2019/10/25 16:39
 * @author: ybzhu
 * @Description： 重写 shiro的 cache
 */
public class RedisCache<K, V> implements Cache<K, V> {

    @Autowired
    private RedisTemplate redisTemplate;

    private String prefix = "shiro:auth:";

    public String getPrefix() {
        return prefix + cacheKey + ":";
    }

    private String cacheKey;

    public RedisCache(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public RedisCache(RedisTemplate redisTemplate, String cacheKey) {
        this.redisTemplate = redisTemplate;
        this.cacheKey = cacheKey;
    }

    /**
     * 获取 缓存
     *
     * @param k
     * @return
     * @throws CacheException
     */
    @Override
    public V get(K k) throws CacheException {
        if (k == null) {
            return null;
        }
        String bytes = getBytesKey(k);
        return (V) redisTemplate.opsForValue().get(bytes);

    }

    /**
     * 更新缓存
     *
     * @param k
     * @param v
     * @return
     * @throws CacheException
     */
    @Override
    public V put(K k, V v) throws CacheException {
        if (k == null || v == null) {
            return null;
        }

        String bytes = getBytesKey(k);
        redisTemplate.opsForValue().set(bytes, v);
        return v;
    }

    /**
     * 删除缓存
     *
     * @param k
     * @return
     * @throws CacheException
     */
    @Override
    public V remove(K k) throws CacheException {
        if (k == null) {
            return null;
        }
        String bytes = getBytesKey(k);
        V v = (V) redisTemplate.opsForValue().get(bytes);
        redisTemplate.delete(bytes);
        return v;
    }

    /**
     * 清除缓存
     *
     * @throws CacheException
     */
    @Override
    public void clear() throws CacheException {
        redisTemplate.getConnectionFactory().getConnection().flushDb();

    }

    /**
     * 获取缓存大小
     *
     * @return
     */
    @Override
    public int size() {
        return redisTemplate.getConnectionFactory().getConnection().dbSize().intValue();
    }

    /**
     * @return
     */
    @Override
    public Set<K> keys() {
        String bytes = getPrefix() + "*";
        Set<byte[]> keys = redisTemplate.keys(bytes);
        Set<K> sets = new HashSet<>();
        for (byte[] key : keys) {
            sets.add((K) key);
        }
        return sets;
    }

    @Override
    public Collection<V> values() {
        Set<K> keys = keys();
        List<V> values = new ArrayList<>(keys.size());
        for (K k : keys) {
            values.add(get(k));
        }
        return values;
    }

    private String getBytesKey(K key) {
        if (key instanceof PrincipalCollection) {
            User primaryPrincipal = (User) ((PrincipalCollection) key).getPrimaryPrincipal();
            return this.getPrefix()+primaryPrincipal.getUsername();
        } else {
            return this.getPrefix() + key;
        }

    }




}
